﻿define([
    "dojo/_base/declare"
    , "dojo/_base/array"
    , "dojo/_base/connect"
    , "dojo/dom-construct"
    , "dojo/dom-style"
    , "esri/domUtils"
    , "esri/lang"
    , "esri/layers/layer"
    , "esri/geometry/Point"
  ], function (
    declare
    , ArrayUtils
    , ConnectUtils
    , DomConstructUtils
    , DomStyleUtils
    , DomUtils
    , esriLang
    , Layer
    , Point
  ) {

      var getPointList = function (map, points) {
          var pointList = [];
          var point;
          for (var i = 0; i < points.length; i++) {
              point = points[i];
              pointList.push({
                  pixel: map.toScreen(point)
              });
          };
          return pointList;
      };

      var getLineDashArgumentsList = function (size) {
          var lineDashArgumentsList = [];
          lineDashArgumentsList.push([size, 0, 0]);
          for (var i = 1; i < size; i++) {
              lineDashArgumentsList.push([0, i, size - i]);
          };
          lineDashArgumentsList.push([0, size, 0]);
          for (var i = 1; i < size; i++) {
              lineDashArgumentsList.push([i, size - i, 0]);
          };
          return lineDashArgumentsList;
      };

      var TrajectoryLayer = declare([Layer], {

          constructor: function (options) {
              //this.inherited(arguments, [options]);

              this._map = null; //地图对象
              this._element = null; //图层dom元素
              this._context = null; //图层dom元素
              this._animateInterval = null; //动画定时器
              this._connects = []; //事件集合
              this.graphics = [];

              this.loaded = true;
              this.onLoad(this);
          }

          , _setMap: function (map, layersElement) {
              //map.addLayer会触发
              //console.log("_setMap");

              this._map = map;

              this._element = DomConstructUtils.create("canvas", {
                  width: map.width + "px",
                  height: map.height + "px",
                  style: "position: absolute; left: 0px; top: 0px;"
              }, layersElement);
              this._context = this._element.getContext("2d");

              this._connects.push(ConnectUtils.connect(this, "onVisibilityChange", this, this._visibilityChangeHandler));
              this._connects.push(ConnectUtils.connect(map, "onPan", this, this._panHandler));
              //this._connects.push(connect.connect(map, "onZoomStart", this, this.clear));
              this._connects.push(ConnectUtils.connect(map, "onExtentChange", this, this._extentChangeHandler));

              return this._element;
          }

          , _unsetMap: function (map, layersElement) {
              //map.removeLayer会触发
              //console.log("_unsetMap");
              ArrayUtils.forEach(this._connects, ConnectUtils.disconnect, this);

              this.clear();

              if (this._element) {
                  this._element.parentNode.removeChild(this._element);
              };

              this._map = null;
              this._element = null;
              this._context = null;
              this._connects = null;
              this.graphics = null;
          }

          , _visibilityChangeHandler: function (visible) {
              if (visible) {
                  DomUtils.show(this._element);
              } else {
                  DomUtils.hide(this._element);
              };
          }

          , _panHandler: function (delta, extent) {
              DomStyleUtils.set(this._element, { left: extent.x + "px", top: extent.y + "px" });
          }

          , _extentChangeHandler: function (extent, delta) {
              //console.log("_extentChangeHandler");
              DomStyleUtils.set(this._element, { left: "0px", top: "0px" });

              this._refresh();
          }

          , clearInterval: function () {
              clearInterval(this._animateInterval);
          }
          , clearCanvas: function () {
              this._context.clearRect(0, 0, this._map.width, this._map.height);
          }
          , clear: function () {
              //console.log("clear");
              this.clearInterval();
              this.clearCanvas();
              this.graphics = [];
          }


          , add: function (line) {
              this.graphics.push(line);

              this._refresh();
          }

          , _draw: function (line) {
              var map = this.getMap();
              if (map == null) {
                  return;
              };

              var pointList = line._pointList;
              var lineDashArguments = line._lineDashArguments;
              //console.log(lineDashArguments);
              this._context.setLineDash(lineDashArguments);
              this._context.beginPath();
              this._context.lineWidth = line.lineWidth;
              this._context.strokeStyle = line.lineStyle;
              this._context.moveTo(pointList[0].pixel.x, pointList[0].pixel.y);
              for (var i = 0, len = pointList.length; i < len; i++) {
                  this._context.lineTo(pointList[i].pixel.x, pointList[i].pixel.y);
              }
              this._context.stroke();
          }

          , _refresh: function () {
              //console.log("_refresh");
              var map = this.getMap();
              if (map == null) {
                  return;
              };

              this.clearInterval();
              this.clearCanvas();

              if (this.graphics.length < 1) {
                  return;
              };

              var line;
              for (var i = 0; i < this.graphics.length; i++) {
                  line = this.graphics[i];
                  line.geometry = line.geometry || {};
                  line.geometry.type = line.geometry.type || "points";
                  line.geometry.points = line.points;
                  line._pointList = getPointList(map, line.points);
                  line._lineDashArgumentsList = getLineDashArgumentsList(line.gapWidth);
                  line._lineDashArgumentsIndex = 0;
              };

              var me = this;
              me._animateInterval = setInterval(function () {
                  //                  console.log("Interval");
                  me.clearCanvas();

                  for (var i = 0; i < me.graphics.length; i++) {
                      line = me.graphics[i];
                      if (line._lineDashArgumentsIndex >= line._lineDashArgumentsList.length) {
                          line._lineDashArgumentsIndex = 0;
                      };
                      line._lineDashArguments = line._lineDashArgumentsList[line._lineDashArgumentsIndex];
                      me._draw(line);
                      line._lineDashArgumentsIndex++;
                  };

              }, 100);
          },
          removeLayer:function () {
              this.clear();
          }

      });

      return TrajectoryLayer;
  });